<?php
/**
 * Here is your custom functions.
 */

if (!function_exists('url')) {
    /**
     * 生成URL地址
     * @param string $url
     * @param array $vars
     * @param string $app
     * @return string
     */
    function url($url, $vars = [], $app = '')
    {
        $app = $app ?: request()->app;
        $vars = !empty($vars) ? '?' . http_build_query($vars) : '';

        return '/' . $app . $url . $vars;
    }
}

if (!function_exists('cookie')) {
    /**
     * Cookie管理
     */
    function cookie(string $name, $value = '', $expire = 86400, $path = '/')
    {
        $request = request();
        $response = response();
        if (is_null($value)) {
            // 删除
            $response->cookie($name, null);
        } elseif ('' === $value) {
            // 获取
            $request->cookie($name);
        } else {
            // 设置
            if (!is_string($value)) {
                $value = json_encode($value);
            }
            $response->cookie($name, $value, $expire, $path);
        }
    }
}

if (!function_exists('cache')) {
    /**
     * 缓存管理
     */
    function cache(string $name = null, $value = '', $options = null, $tag = null)
    {
        if (is_null($name)) {
            return '';
        }

        $cache = new \support\think\Cache();
        if ('' === $value) {
            // 获取缓存
            return 0 === strpos($name, '?') ? $cache::has(substr($name, 1)) : $cache::get($name);
        } elseif (is_null($value)) {
            // 删除缓存
            return $cache::delete($name);
        }

        // 缓存数据
        if (is_array($options)) {
            $expire = $options['expire'] ?? null; //修复查询缓存无法设置过期时间
        } else {
            $expire = $options;
        }

        if (is_null($tag)) {
            return $cache::set($name, $value, $expire);
        } else {
            return $cache::tag($tag)->set($name, $value, $expire);
        }
    }
}

if (!function_exists('__')) {
    /**
     * 获取语言变量值
     */
    function __($id, $parameters = [], $domain = null, $locale = null)
    {
        return trans($id, $parameters, $domain, $locale);
    }
}

/**
 * 判断是否 SSL 协议（兼容反向代理）
 */
function is_ssl() {
    // 标准 HTTPS 检查
    if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) {
        return true;
    }
    // 标准端口检查（443 是 HTTPS 默认端口）
    if (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) {
        return true;
    }
    // 反向代理/CDN 检查（如 Cloudflare、Nginx 反向代理）
    if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' === strtolower($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
        return true;
    }
    // 某些代理服务器使用 HTTP_X_FORWARDED_SSL
    if (isset($_SERVER['HTTP_X_FORWARDED_SSL']) && 'on' === strtolower($_SERVER['HTTP_X_FORWARDED_SSL'])) {
        return true;
    }

    return false;
}

/**
 * 返回带协议的域名
 */
function get_host()
{
    $host = $_SERVER['HTTP_HOST'];
    $protocol = is_ssl() ? 'https://' : 'http://';

    return $protocol . $host;
}

/**
 * 返回带域名的路径
 */
function asset($path)
{
    //$protocol = is_ssl() ? 'https://' : 'http://';
    if (request()->header('x-forwarded-proto') == 'https') {
        $protocol = 'https://';
    } else {
        $protocol = 'http://';
    }
    //$host = getenv('APP_HOST');
    $host = request()->host();
    $rootPath = '/';
    if (substr($path, 0, 1) == '/') {
        $url = $protocol . $host . $path;
    } else {
        $url = $protocol . $host . $rootPath . $path;
    }

    return $url;
}

/**
 * 获取客户端IP
 */
function get_client_ip()
{
//    $ip = request()->getRemoteIp();
    $ip = request()->getRealIp();

    return $ip;
}

/**
 * 格式化字节大小【用于数据库备份】
 *
 * @param number $size 字节数
 * @param string $delimiter 数字和单位分隔符
 * @return string 格式化后的带单位的大小
 */
function format_bytes($size, $delimiter = '')
{
    $size = (int)$size;
    $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
    for ($i = 0; $size >= 1024 && $i < 5; $i++) {
        $size /= 1024;
    }

    return round($size, 2) . $delimiter . $units[$i];
}

/**
 * 转化数据库保存的文件路径为可以访问的url
 *
 * @param string $filepath
 * @return string
 */
function full_file_url($filepath)
{
    if ($filepath) {
        if (strpos($filepath, 'http') === 0 || strpos($filepath, 'https') === 0) {
            return $filepath;
        } else {
            if (defined('IS_CRON') && IS_CRON) {
                return config('path.full_upload_path') . $filepath;
            } else {
                return asset(config('path.upload_path') . $filepath);
            }
        }
    } else {
        return asset(config('path.static_path') . 'img/not_image.png');
    }
}

/**
 * 去掉数据库保存的文件路径中 http(s) 等前缀字符
 */
function unfull_file_url($files)
{
    $path = asset(config('path.upload_path'));
    if (is_array($files)) {
        foreach ($files as &$file) {
            if (strpos($file, $path) !== false) {
                $file = str_replace($path, '', $file);
            }
        }
    } else {
        if (strpos($files, $path) !== false) {
            $files = str_replace($path, '', $files);
        }
    }

    return $files;
}

// 生成唯一ID
function get_UUID($prefix = '')
{
    $uuid = md5(uniqid(mt_rand(), true));
    return $prefix . $uuid;
}

/**
 * 生成惟一单号
 * @return string
 */
function create_order_sn()
{
    return date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}

/**
 * 生成订单号
 */
function make_order_no()
{
    //$yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
    //$orderSn = $yCode[intval(date('Y')) - 2019] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));

    $orderSn = date('Ymd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));

    return $orderSn;
}

/**
 * 生成随机数字验证码
 * @param int $len
 * @return bool|string
 */
function random_number($len = 6)
{
    $chars = str_repeat('0123456789', 3);
    // 位数过长重复字符串一定次数
    $chars = str_repeat($chars, $len);
    $chars = str_shuffle($chars);
    $str = substr($chars, 0, $len);

    return $str;
}

/**
 * 生成随机字符串生成
 * @param int $len 长度
 * @param string $type 字串类型：0 字母 1 数字 其它 混合
 * @return string
 */
function random_string($len = 6, $type = '')
{
    $str = '';
    switch ($type) {
        case 0:
            $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
            break;
        case 1:
            $chars = str_repeat('0123456789', 3);
            break;
        case 2:
            $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            break;
        case 3:
            $chars = 'abcdefghijklmnopqrstuvwxyz';
            break;
        case 4:
            $chars = 'ABCDEFGHIJKMNPQRSTUVWXYZ23456789';
            break;
        case 5:
            $chars = 'abcdefghijkmnpqrstuvwxyz23456789';
            break;
        default :
            // 默认去掉了容易混淆的字符oOLl和数字01
            $chars = 'ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789';
            break;
    }
    // 位数过长重复字符串一定次数
    if ($len > 10) {
        $chars = $type == 1 ? str_repeat($chars, $len) : str_repeat($chars, 5);
    }
    $chars = str_shuffle($chars);
    $str = substr($chars, 0, $len);

    /*
    $charsLen = strlen($chars);
    $str = '';
    for ($i = 0; $i < $len; $i++) {
        $str .= $chars[mt_rand(0, $charsLen - 1)];
    }
    */

    return $str;
}

/**
 * 获取文件扩展名
 *
 * @param string $filename
 * @return string
 */
function get_file_extension($filename)
{
    $pathinfo = pathinfo($filename);

    return strtolower($pathinfo['extension']);
}

/**
 * 递归删除文件
 *
 * @param string $dir 文件夹路径
 * @param string /array $fileType 文件类型（.html/.php）
 */
function del_file($dir, $fileType = '')
{
    if (is_dir($dir)) {
        $files = scandir($dir);
        // 打开目录，列出目录中的所有文件并去掉 . 和 ..
        foreach ($files as $filename) {
            if ($filename == '.' || $filename == '..') {
                continue;
            }
            if (!is_dir($dir . '/' . $filename)) {
                if (!empty($fileType)) {
                    if (is_array($fileType)) {
                        // 正则匹配指定文件
                        if (preg_match($fileType[0], $filename)) {
                            unlink($dir . '/' . $filename);
                        }
                    } elseif (stristr($filename, $fileType) != false) {
                        // 指定包含某些字符串的文件
                        unlink($dir . '/' . $filename);
                    }
                } else {
                    unlink($dir . '/' . $filename);
                }
            } else {
                // 递归删除
                del_file($dir . '/' . $filename, $fileType);
            }
        }
        // 删除完子文件和子文件夹后再删除父文件夹
        rmdir($dir);
    } elseif (file_exists($dir)) {
        unlink($dir);
    }
}

/**
 * 把返回的数据集转换成Tree
 *
 * @param array $list 要转换的数据集
 * @param string $pk 主键字段
 * @param string $pid parent标记字段
 * @param string $child
 * @param int $root
 * @param bool $isChild
 * @return array
 */
function list_to_tree($list, $pk = 'id', $pid = 'parent_id', $child = 'children', $root = 0, $isChild = false)
{
    // 创建Tree
    $tree = [];
    if (is_array($list)) {
        // 创建基于主键的数组引用
        $refer = [];
        foreach ($list as $key => $item) {
            $refer[$item[$pk]] = &$list[$key];
        }
        foreach ($list as $key => $item) {
            // 判断是否存在parent
            $parentId = $item[$pid];
            if ($root === $parentId) {
                if ($isChild && !isset($list[$key][$child])) {
                    $list[$key][$child] = []; // 子集为空
                }
                $tree[] = &$list[$key];
            } else {
                if (isset($refer[$parentId])) {
                    $parent = &$refer[$parentId];
                    if ($isChild && !isset($list[$key][$child])) {
                        $list[$key][$child] = []; // 子集为空
                    }
                    $parent[$child][] = &$list[$key];
                }
            }
        }
    }

    return $tree;
}

/**
 * 首字母头像
 *
 * @param $text
 * @return string
 */
function letter_avatar($text)
{
    $total = unpack('L', hash('adler32', $text, true))[1];
    $hue = $total % 360;
    list($r, $g, $b) = hsv2rgb($hue / 360, 0.3, 0.9);

    $bg = "rgb({$r},{$g},{$b})";
    $color = '#ffffff';
    $first = mb_strtoupper(mb_substr($text, 0, 1));
    $src = base64_encode('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="100" width="100"><rect fill="' . $bg . '" x="0" y="0" width="100" height="100"></rect><text x="50" y="50" font-size="50" text-copy="fast" fill="' . $color . '" text-anchor="middle" text-rights="admin" dominant-baseline="central">' . $first . '</text></svg>');
    $value = 'data:image/svg+xml;base64,' . $src;
    return $value;
}

function hsv2rgb($h, $s, $v)
{
    $r = $g = $b = 0;

    $i = floor($h * 6);
    $f = $h * 6 - $i;
    $p = $v * (1 - $s);
    $q = $v * (1 - $f * $s);
    $t = $v * (1 - (1 - $f) * $s);

    switch ($i % 6) {
        case 0:
            $r = $v;
            $g = $t;
            $b = $p;
            break;
        case 1:
            $r = $q;
            $g = $v;
            $b = $p;
            break;
        case 2:
            $r = $p;
            $g = $v;
            $b = $t;
            break;
        case 3:
            $r = $p;
            $g = $q;
            $b = $v;
            break;
        case 4:
            $r = $t;
            $g = $p;
            $b = $v;
            break;
        case 5:
            $r = $v;
            $g = $p;
            $b = $q;
            break;
    }

    return [
        floor($r * 255),
        floor($g * 255),
        floor($b * 255)
    ];
}

/**
 * 自定义日志
 *
 * @param string $message 日志信息
 * @param string $level 日志级别
 * @param string $folder 文件夹
 */
function log_info($message, $level = 'INFO', $folder = 'default')
{
    $timezone = date_default_timezone_get();
    date_default_timezone_set('Asia/Shanghai');
    $path = base_path() . '/runtime/logs/' . $folder . '/' . date('Ym');
    if (!file_exists($path)) {
        mkdir($path, 0777, true);
    }
    $file = $path . '/' . date('d') . '.log';
    // 修改文件权限
    //chmod($file, 0777);
    $f = fopen($file, 'a+');
    $logInfo = '[' . date('Y-m-d H:i:s') . "]\r\n";
    $logInfo .= $level . ': ' . $message;
    fwrite($f, $logInfo . "\r\n\r\n");
    fclose($f);
    date_default_timezone_set($timezone);
}


/**
 * API接口输出数据
 */
function api_response($status, $msg = '', $data = [], $error = '', $code = 200)
{
    $response = [
        'status' => $status,
        'code' => $code,
        'msg' => $msg,
        'data' => $data,
        'error' => $error,
    ];

    return json($response);
}